package com.learning.dynamic.executor.listener.adapter;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.learning.dynamic.executor.config.DynamicProperties;
import com.learning.dynamic.executor.configcenter.AbstractDynamicConfigCenter;
import com.learning.dynamic.executor.configcenter.adapter.NacosConfigCenterAdapter;
import com.learning.dynamic.executor.exception.ListenerAddException;
import com.learning.dynamic.executor.executor.DynamicExecutor;
import com.learning.dynamic.executor.listener.DynamicConfigCenterListener;
import com.learning.dynamic.executor.utils.SpringBeanUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ByteArrayResource;

import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @author Wang Xu
 * @date 2023/11/7
 */
public class NacosListerAdapter extends NacosConfigCenterAdapter implements DynamicConfigCenterListener<ConfigService>, Listener {
    @NacosInjected
    public NacosListerAdapter(ConfigService configService) {
        super(configService);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        addListener();
    }

    @Override
    public Executor getExecutor() {
        return Executors.newFixedThreadPool(1);
    }

    @Override
    public void receiveConfigInfo(String configInfo) {
        LOGGER.info("接受到nacos配置变更通知，configInfo: {}", configInfo);
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        yamlPropertiesFactoryBean.setResources(new ByteArrayResource(configInfo.getBytes()));
        Binder binder = new Binder(new MapConfigurationPropertySource(yamlPropertiesFactoryBean.getObject()));
        BindResult<DynamicProperties> bindResult = binder.bind("dynamic.executor", Bindable.of(DynamicProperties.class));
        DynamicProperties dynamicProperties = bindResult.orElse(new DynamicProperties());

        if (Objects.nonNull(dynamicProperties.getDynamicExecutorPropertiesList())) {
            dynamicProperties.getDynamicExecutorPropertiesList().forEach(de -> {
                DynamicExecutor dynamicExecutor = null;
                try {
                    dynamicExecutor = SpringBeanUtil.getBean(de.getPoolName(), DynamicExecutor.class);
                } catch (BeansException e) {
                    LOGGER.error("获取:{} bean失败，", de.getPoolName(), e);
                    return;
                }
                if (!de.getCorePoolSize().equals(dynamicExecutor.getCorePoolSize())) {
                    dynamicExecutor.setCorePoolSize(de.getCorePoolSize());
                }
                if (!de.getMaximumPoolSize().equals(dynamicExecutor.getMaximumPoolSize())) {
                    dynamicExecutor.setMaximumPoolSize(de.getMaximumPoolSize());
                }
            });
        }

    }

    @Override
    public void addListener() throws ListenerAddException {
        try {
            super.getConfigService().addListener("nacos-dy-ds-conf.yml", "group-test1",  this);
            LOGGER.info("dataId: {}, group: {}, addListener finished", "nacos-dy-ds-conf.yml", "group-test1");
        } catch (NacosException e) {
            LOGGER.info("dataId: {}, group: {}, addListener failed", "nacos-dy-ds-conf.yml", "group-test1", e);
            throw new ListenerAddException(e);
        }
    }
}